transform.Translate ではなく、Rigidbody.MovePosition を使用して移動させると、物理エンジンとの整合性が保たれ、壁にめりこむ不具合が解消される場合があります。
なお、Rigidbody.MovePosition は物理エンジンと連携して動作するため、原則として FixedUpdate で使用することが推奨されています。
Update と FixedUpdate の違い
Update メソッド
呼び出し頻度: フレームごとに一度呼び出され、フレームレートに依存します。
用途: プレイヤーの入力処理、アニメーション更新、UI更新など、フレームごとに実行する処理に使用します。
FixedUpdate メソッド
呼び出し頻度: 一定の時間間隔(デフォルトでは0.02秒)で呼び出され、物理演算の更新と同期しています。そのため、フレームレートに依存しません。
用途: 物理演算、Rigidbody の移動や力の加算など、物理ベースの処理に使用します。物理エンジンの更新と一致しているため、安定した動作が可能です。
以下のコードは、上下キーで前後に移動し、左右キーで回転、スペースキーでジャンプするサンプルコードです。プレイヤーにアタッチしてください。Rigidbodyコンポーネントも必要です。
using UnityEngine;
public class Player : MonoBehaviour
{
public float moveSpeed = 5f; // 移動速度
public float turnSpeed = 100f; // 回転速度
public float jumpForce = 5f; // ジャンプの力
private Rigidbody rb;
private bool isGrounded; // 地面に接しているかどうかを判定するフラグ
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
// ジャンプ処理 (Updateでキー入力を確認)
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isGrounded = false; // ジャンプ中は地面にいないのでフラグをfalseに
}
}
void FixedUpdate()
{
// 前後の移動(上下キー)
float moveInput = Input.GetAxis("Vertical"); // 上下キーの入力(-1 ~ 1)
Vector3 moveDirection = transform.forward * moveInput * moveSpeed * Time.fixedDeltaTime;
// 左右の回転(左右キー)
float turnInput = Input.GetAxis("Horizontal"); // 左右キーの入力(-1 ~ 1)
Quaternion turnRotation = Quaternion.Euler(0f, turnInput * turnSpeed * Time.fixedDeltaTime, 0f);
// Rigidbodyを使った移動と回転
rb.MovePosition(rb.position + moveDirection); // 前後の移動
rb.MoveRotation(rb.rotation * turnRotation); // 左右の回転
}
// 地面との接触を確認
private void OnCollisionEnter(Collision collision)
{
// 地面に触れているか確認(タグを使うのがおすすめ)
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true; // 地面に触れていればフラグをtrueに
}
}
}